package adapter;

import hospital.Hospital;

import java.io.File;

import java.util.ArrayList;
import java.util.List;

import main.World;
import movement.Location;

import unit.Unit;

import emergency.Disaster;
import emergency.Emergency;

import be.kuleuven.cs.swop.api.EmergencyDispatchException;
import be.kuleuven.cs.swop.api.EmergencyState;
import be.kuleuven.cs.swop.api.IEmergency;
import be.kuleuven.cs.swop.api.IEvent;
import be.kuleuven.cs.swop.api.IHospital;
import be.kuleuven.cs.swop.api.ITime;
import be.kuleuven.cs.swop.api.IUnit;
import be.kuleuven.cs.swop.api.IUnitConfiguration;
import be.kuleuven.cs.swop.api.UnitState;

public class AEmergencyDispatch implements be.kuleuven.cs.swop.api.IEmergencyDispatchApi {

	//private DispatchCenter dispatchCenter;
	private World world;
	
	public AEmergencyDispatch(String args[]){
		world=new World(args);
		//world.startup();
	}
	
	
	/**
	 * Method for advancing the time 
	 * 
	 * @param time 
	 * 			The ITime you want to advance the clock
	 * 
	 * @throws Exception, if the clock cannot be advanced
	 */
	@Override
	public void advanceTime(ITime time) throws EmergencyDispatchException {
		try{
			world.getDispatchCenter().getClock().advanceTime(time.getMinutes()+time.getHours()*60);
		}
		catch(Exception e){
			throw new EmergencyDispatchException("Clock cannot be advanced! ("+e+")");
		}
	}

	@Override
	public void assignUnits(IUnitConfiguration configuration)
			throws EmergencyDispatchException {
		AUnitConfiguration conf = (AUnitConfiguration)configuration;
		conf.getEmergency().getEmergency().getSuggestion(world.getDispatchCenter().getGarage());
		for(Unit u : conf.getSuggestie()){
			
			u.assignEmergency(conf.getEm());
		}
		
	}

	@Override
	public void cancelEmergency(IEmergency emergency)
			throws EmergencyDispatchException {
		AEmergency em = (AEmergency)emergency;
		em.getEmergency().cancelEmergency();
		
	}

	@Override
	public void clearSystem() {
		world=new World(null);
	}

	@SuppressWarnings("unused")
	@Override
	public void createDisaster(String description, List<IEmergency> emergencies)
			throws EmergencyDispatchException {
		try{
			ArrayList<Emergency> toeTeVoegen= new ArrayList<Emergency>();
			AEmergency aemergency;
			for(IEmergency aem : emergencies){
				aemergency = (AEmergency)aem;
				toeTeVoegen.add(aemergency.getEmergency());
			}
			Disaster disaster = new Disaster(world.getDispatchCenter(), toeTeVoegen, description);
		}
		catch(Exception e){
			throw new EmergencyDispatchException(e.toString());
		}
		
	}

	@Override
	public List<IEmergency> getListOfDisasters(EmergencyState state)
			throws EmergencyDispatchException {
		AEmergency aem;
		List<IEmergency> aemergencies = new ArrayList<IEmergency>();
		for(Emergency e : world.getDispatchCenter().getEmergenciesFromType("disaster")){
			aem = new AEmergency(e);
			if(aem.getState()==state)
				aemergencies.add(aem);
		}
		return aemergencies;
	}

	@SuppressWarnings("static-access")
	@Override
	public List<IEmergency> getListOfEmergencies(EmergencyState state)
			throws EmergencyDispatchException {
		List<Emergency> emergencyList = new ArrayList<Emergency>();
		List<IEmergency> aemergencyList = new ArrayList<IEmergency>();
		if(state==state.CANCELLED){
			emergencyList = world.getDispatchCenter().getEmergencyboard().getEmergenciesCancelled();
		}
		else if(state==state.COMPLETED){
			emergencyList=world.getDispatchCenter().getEmergencyboard().getEmergenciesCompleted();
		}
		else if(state==state.RESPONDED){
			emergencyList=world.getDispatchCenter().getEmergencyboard().getEmergenciesInProgress();
		}
		else if(state==state.UNHANDLED){
			emergencyList=world.getDispatchCenter().getEmergencyboard().getEmergenciesRecorded();
		}
		else{
			emergencyList=world.getDispatchCenter().getEmergencyboard().getEmergencies();
		}
		for(Emergency e : emergencyList)
			aemergencyList.add(new AEmergency(e));
		return aemergencyList;
		
	}

	@Override
	public List<IHospital> getListOfHospitals() {
		List<IHospital> hospitals = new ArrayList<IHospital>();
		for(Hospital h : world.getDispatchCenter().getHospitals())
			hospitals.add(new AHospital(h));
		return hospitals;
	}

	@Override
	public List<IUnit> getListOfUnits(UnitState state)
			throws EmergencyDispatchException {
		List<IUnit> aunits = new ArrayList<IUnit>();
		for(Unit u : world.getDispatchCenter().getGarage().getUnitsClone()){
			AUnit temp = new AUnit(u);
			if(temp.getState()==state)
				aunits.add(temp);
		}		
		return aunits;
			
	}

	@Override
	public AUnitConfiguration getUnitConfiguration(IEmergency emergency)
			throws EmergencyDispatchException {
		AEmergency aem = (AEmergency)emergency;
		return new AUnitConfiguration(aem.getEmergency(), world.getDispatchCenter().getGarage());
	}

	@Override
	public void indicateEndOfTask(IUnit unit, IEmergency emergency)
			throws EmergencyDispatchException {
		try{
			AEmergency aem = (AEmergency)emergency;
			AUnit aunit = (AUnit)unit;
			if(aunit.getUnit().getEmergency()!=aem.getEmergency()){
				throw new EmergencyDispatchException("de meegegeven emergency is niet de emergency van deze unit!");
			}
			aunit.getUnit().endEmergency();
		}
		catch(Exception e){
			throw new EmergencyDispatchException(e.toString());	
		}
	}

	@Override
	public void indicateProblem(IUnit unit) throws EmergencyDispatchException {
		AUnit aunit = (AUnit)unit;
		aunit.getUnit().brokeDown();
	}

	@Override
	public void indicateRepair(IUnit unit) throws EmergencyDispatchException {
		AUnit aunit = (AUnit)unit;
		aunit.getUnit().repair();
		
	}

	@Override
	public void loadEnvironment(File file) throws EmergencyDispatchException {
		clearSystem();
		try{
		String[] args = new String[1];
		args[0]=file.getAbsoluteFile().toString();
		world=new World(args);
		}
		catch(Exception e){
			//
		}
		//world.startup();
	}

	@SuppressWarnings("unused")
	@Override
	public void registerNewEvent(IEvent event)
			throws EmergencyDispatchException {
		Location loc = new Location(event.getLocation().getX(), event.getLocation().getY(),"Event");
		emergency.Severity sev = null;
		
		if(event.getSeverity().equals(be.kuleuven.cs.swop.api.Severity.BENIGN))
			sev=emergency.Severity.BENIGN;
		if(event.getSeverity().equals(be.kuleuven.cs.swop.api.Severity.NORMAL))
			sev=emergency.Severity.NORMAL;
		if(event.getSeverity().equals(be.kuleuven.cs.swop.api.Severity.URGENT))
			sev=emergency.Severity.URGENT;
		if(event.getSeverity().equals(be.kuleuven.cs.swop.api.Severity.SERIOUS))
			sev=emergency.Severity.SERIOUS;
		
		if(event instanceof be.kuleuven.cs.swop.events.Fire){
			be.kuleuven.cs.swop.events.Fire afire = (be.kuleuven.cs.swop.events.Fire)event;
			emergency.Fire.Size size = null;
			if(afire.getSize().equals("local"))
					size=emergency.Fire.Size.LOCAL;
			if(afire.getSize().equals("house"))
				size=emergency.Fire.Size.HOUSE;
			if(afire.getSize().equals("facility"))
				size=emergency.Fire.Size.FACILITY;
			emergency.Fire fire = new emergency.Fire(loc, sev, world.getDispatchCenter(), size, afire.isChemical(), afire.getNumberOfInjured(), afire.getNumberOfTrappedPeople());
		}
		
		else if(event instanceof be.kuleuven.cs.swop.events.PublicDisturbance){
			be.kuleuven.cs.swop.events.PublicDisturbance apublicdisturbance = (be.kuleuven.cs.swop.events.PublicDisturbance)event;
			emergency.PublicDisturbance pb = new emergency.PublicDisturbance(loc, sev, world.getDispatchCenter(), apublicdisturbance.getNumberOfPeople());
		}
		
		else if(event instanceof be.kuleuven.cs.swop.events.Robbery){
			be.kuleuven.cs.swop.events.Robbery arobbery = (be.kuleuven.cs.swop.events.Robbery)event;
			emergency.Robbery robbery = new emergency.Robbery(loc, sev, world.getDispatchCenter(), arobbery.isArmed(), arobbery.isInProgress());
		}	
		
		else if(event instanceof be.kuleuven.cs.swop.events.TrafficAccident){
			be.kuleuven.cs.swop.events.TrafficAccident ata = (be.kuleuven.cs.swop.events.TrafficAccident)event;
			emergency.TrafficAccident ta = new emergency.TrafficAccident(loc, sev, world.getDispatchCenter(),ata.getNumberOfCars(),ata.getNumberOfInjured());
		}	
	}

	@Override
	public void selectHospital(IUnit unit, IHospital hospital)
			throws EmergencyDispatchException {
		try{
			AUnit aunit = (AUnit) unit;
			AHospital ahospital = (AHospital) hospital;
			aunit.getUnit().assignHospital(ahospital.getHospital());
		}
		catch(Exception e){
			throw new EmergencyDispatchException(e.toString());
		}
		
	}

	@Override
	public void withdrawUnit(IUnit unit, IEmergency emergency)
			throws EmergencyDispatchException {
		AUnit aunit = (AUnit) unit;
		AEmergency aemergency = (AEmergency) emergency;
		try {
			if(aunit.getUnit().getEmergency()!=aemergency.getEmergency())
				throw new EmergencyDispatchException("emergency komt niet overeen met de unit");
			aunit.getUnit().revokeUnit();
		} catch (IllegalAccessException e) {
			throw new EmergencyDispatchException(e.toString());
		}
		
	}
	
}
